<template>
    <el-scrollbar height="100%" style="width: 100%;" @click="handlePanelClick">
        <ul class="resource-wrapper">
            <li class="resource-item" v-for="(item, index) in dataList"
                @click.stop="handleNodeClick(item, index, $event)" :key="index"
                @contextmenu.stop="onContextMenu($event, item)" @dblclick="handleNodeDblclick(item, index, $event)"
                :class="{ 'highlight': highlightNode?.id == item.id, 'edit_mode': editNode?.id == item.id }"
                :title="item.name">
                <div>
                    <IconPlus :name="item.icon || 'unknownfile'" :size="32" />
                    <div class="title-wrapper">
                        <span class="title" v-if="editNode?.id != item.id"> {{ item.name }}</span>
                        <span ref="inputRef" v-else contenteditable="true" class="input"
                            @keydown.enter="handleInputEnter(item, $event)">
                            {{ item.name }}
                        </span>
                    </div>
                </div>
            </li>
        </ul>
    </el-scrollbar>
</template>

<script setup>
const dataList = defineModel({
    type: Array,
    required: false,
    default: {
        id: undefined,
        name: "新建文件夹",
    }
})

//定义当前活跃节点
const activeNode = ref();
//定义当前高亮节点
const highlightNode = ref();
//定义当前编辑中的节点
const editNode = ref();
const inputRef = ref();

const clickDelay = 250 // 延迟时间，可以根据需求调整
let clickTimer = null
const { proxy } = getCurrentInstance()
const emits = defineEmits(['nodeClick', 'contextMenu', 'nodeDblclick', 'nodeChange', 'closeEdit'])

//节点双击事件
const handleNodeDblclick = (node, index, event) => {
    // 清除之前的定时器
    if (clickTimer) clearTimeout(clickTimer)
    emits('nodeDblclick', node, index, event);
    setActiveNode();
    setHighlight();
}

//节点单击事件
const handleNodeClick = (node, index, event) => {
    // 清除之前的定时器，防止多次点击叠加
    if (clickTimer) {
        clearTimeout(clickTimer);
    }

    // 如果存在活跃节点，并且当前节点与活跃节点相同
    if (activeNode.value && node.id === activeNode.value.id) {
        // 延时进入编辑模式
        clickTimer = setTimeout(() => {
            setEdit(node);
            clickTimer = null;
        }, clickDelay);
    } else {
        setActiveNode(node);
        // 否则进入高亮模式，并触发点击事件
        setHighlight(node);
        closeEdit();
        emits('nodeClick', node, index, event);
    }
};

//进入编辑模式
const setEdit = (node) => {
    editNode.value = node;
    if (node) {
        nextTick(() => {
            let inputEl = inputRef.value[0];
            inputEl.focus();
            let func = node.isFolder ? selectAllText : selectFileName;
            func(inputEl);
        })
    }
}

//编辑校验
const closeValidate = (name, node) => {
    const trimmed = name.trim();
    console.log(node);
    const maxLength = node?.isFolder ? 10 : 50;
    if (!trimmed) {
        proxy.$modal.msgWarning("名称不能为空");
        return false;
    }
    if (trimmed.length > maxLength) {
        proxy.$modal.msgWarning(`名称过长，建议${maxLength}个字符内`);
        return false;
    }
    return true;
};

//编辑关闭事件
const closeEdit = () => {
    if (editNode.value) {
        let inputEl = inputRef.value[0];
        let text = inputEl.textContent;
        let haschange = text != editNode.value.name;
        let node = editNode.value;
        editNode.value = undefined;
        if (!closeValidate(text, node)) {
            return;
        }
        emits('closeEdit', node, text, haschange);
    }
}

//进入高亮模式
const setHighlight = (node) => {
    if (highlightNode.value !== node) {
        if (highlightNode.value) {
            highlightNode.value.highlight = false;
        }
        highlightNode.value = node;
    }
}

const setActiveNode = (node) => {
    activeNode.value = node;
}

//编辑内按enter事件
const handleInputEnter = (node, event) => {
    event.preventDefault();
    closeEdit();
}

const selectAllText = (element) => {
    const range = document.createRange();
    range.selectNodeContents(element);
    const selection = window.getSelection();
    selection.removeAllRanges();
    selection.addRange(range);
};

const selectFileName = (element) => {
    if (element) {
        const text = element.textContent;
        let fileName = text;
        const lastDotIndex = text.lastIndexOf('.');
        if (lastDotIndex !== -1) {
            fileName = text.slice(0, lastDotIndex);
        }

        const selection = window.getSelection();
        const range = document.createRange();

        // 找到文件名在文本中的起始和结束位置
        const startIndex = text.indexOf(fileName);
        const endIndex = startIndex + fileName.length;

        // 设置范围为文件名部分
        range.setStart(element.firstChild, startIndex);
        range.setEnd(element.firstChild, endIndex);

        // 清除当前选择
        selection.removeAllRanges();
        // 添加新的选择范围
        selection.addRange(range);
    }
}


//右键菜单事件
const onContextMenu = ($event, item) => {
    setActiveNode(item);
    setHighlight(item);
    emits('contextMenu', $event, item)
}

// 面板点击事件
const handlePanelClick = () => {
    setHighlight();
    setActiveNode();
    closeEdit();
}

//向外通知节点改变
const noticeNodeChange = (currentNode, oldNode) => {
    // console.log("节点改变：" + oldNode?.name + "->" + currentNode?.name)
    emits('nodeChange', currentNode, oldNode);
}

watch(activeNode, (current, old) => {
    noticeNodeChange(current, old);
})


defineExpose({
    setRename: setEdit
})

onMounted(() => {

})
</script>
<style lang="scss" scoped>
ul,
li {
    list-style: none;
    padding: 0;
    margin: 0;
    position: relative;
}


.resource-wrapper {
    display: flex;
    gap: 20px;
    flex-wrap: wrap;

    .resource-item {
        font-size: 10px;
        text-align: center;
        padding: 8px;
        padding-bottom: 0;
        width: 70px;
        cursor: pointer;
        position: relative;

        &.highlight {
            background: var(--el-color-info-light-8) !important;
        }

        &.edit_mode {
            background: var(--el-color-info-light-8) !important;

            .input {
                padding: 4px 2px;
                width: 100%;
                border: 1px solid;
                display: inline-block;
                line-height: 20px;
                position: absolute;
                top: 0;
                left: 0;
                width: 100%;
                // border: 1px solid var(--el-border-color);
            }
        }

        &:hover {
            background: var(--el-color-info-light-9);
        }


        .title-wrapper {
            position: relative;
            margin-top: 2px;
        }

        .title {
            border: 1px solid transparent;
            padding: 4px 2px;
            display: block;
            width: 100%;
            line-height: 20px;
            word-wrap: break-word;
            display: inline-block;
            white-space: nowrap;
            overflow: hidden;
            text-overflow: ellipsis;
            user-select: none;
        }
    }
}
</style>